package org.nci.platform.workflow.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.core.util.PageUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import gh.priv.general.common.exception.ServiceException;
import gh.priv.general.common.vo.PageResult;
import org.nci.platform.workflow.dto.SysExpressionPageQuery;
import org.nci.platform.workflow.dto.SysExpressionQuery;
import org.nci.platform.workflow.entity.SysExpression;
import org.nci.platform.workflow.mapper.SysExpressionMapper;
import org.nci.platform.workflow.service.FlowableMapperService;
import org.nci.platform.workflow.service.ISysExpressionService;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 流程达式Service业务层处理
 *
 * @author ruoyi
 * @date 2022-12-12
 */
@Service
public class SysExpressionServiceImpl implements ISysExpressionService {
    @Resource
    private FlowableMapperService flowableMapperService;

    @Override
    public List<SysExpression> list(SysExpressionQuery query) {
        return flowableMapperService.executeQuery(SysExpressionMapper.class,mapper->mapper.list(query));
    }

    @Override
    public PageResult<SysExpression> page(SysExpressionPageQuery query) {
        List<SysExpression> sysExpressions = flowableMapperService.executeQuery(SysExpressionMapper.class,mapper->mapper.page(query));
        Long count = flowableMapperService.executeQuery(SysExpressionMapper.class,mapper->mapper.pageCount(query));
        return PageResult.of(sysExpressions, count, query.getPageSize(), query.getPageNum());
    }

    @Override
    public void export(HttpServletResponse response, SysExpressionQuery query) {
        Long count = flowableMapperService.executeQuery(SysExpressionMapper.class,mapper->mapper.pageCount(query));
        int totalPage = PageUtil.totalPage(count, 80000);
        String fileName = URLEncodeUtil.encode("表达式_" + System.currentTimeMillis() + ".xlsx", StandardCharsets.UTF_8);
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
        try (OutputStream outputStream = response.getOutputStream()) {
            // 6. 创建ExcelWriter
            ExcelWriter excelWriter = EasyExcel.write(outputStream, SysExpression.class)
                    .autoCloseStream(false)
                    .build();
            SysExpressionPageQuery sysExpressionPageQuery = BeanUtil.copyProperties(query, SysExpressionPageQuery.class);
            sysExpressionPageQuery.setPageSize(80000);
            // 7. 分页查询并写入Excel
            for (int pageNum = 1; pageNum <= totalPage; pageNum++) {
                sysExpressionPageQuery.setPageNum(pageNum);
                // 分页查询数据
                List<SysExpression> pageResult = flowableMapperService.executeQuery(SysExpressionMapper.class,mapper->mapper.page(sysExpressionPageQuery));

                if (pageResult.isEmpty()) {
                    break;
                }

                // 创建工作表（每个分页一个工作表）
                String sheetName = "表达式" + "_" + pageNum;
                WriteSheet writeSheet = EasyExcel.writerSheet(pageNum - 1, sheetName)
                        .head(SysExpression.class)
                        .build();

                // 写入数据
                excelWriter.write(pageResult, writeSheet);

                // 可选：记录进度或添加延迟以避免内存压力
                if (pageNum % 10 == 0) {
                    outputStream.flush();
                }
            }
            if (totalPage == 0) {
                excelWriter.write(new ArrayList<>(), new WriteSheet());
            }
            // 8. 完成并关闭写入器
            excelWriter.finish();
            outputStream.flush();
        } catch (IOException e) {
            throw ServiceException.of(500, e.getMessage());
        }
    }

    @Override
    public SysExpression getById(Long id) {
        SysExpression sysExpressions = flowableMapperService.executeQuery(SysExpressionMapper.class,mapper->mapper.getById(id));
        return sysExpressions;
    }

    @Override
    public void save(SysExpression sysExpression) {
        flowableMapperService.executeUpdate(SysExpressionMapper.class,mapper->mapper.save(sysExpression));
    }

    @Override
    public void updateById(SysExpression sysExpression) {
        flowableMapperService.executeUpdate(SysExpressionMapper.class,mapper->mapper.updateById(sysExpression));
    }

    @Override
    public void removeByIds(List<Long> ids) {
        flowableMapperService.executeUpdate(SysExpressionMapper.class,mapper->mapper.removeByIds(ids));
    }
}
